#include "MyGraphicsView.h"
#include "QGraphicsItem"
#include <QScrollBar>
#include <QMenu>

MyGraphicsView::MyGraphicsView(QWidget *parent)
    : QGraphicsView(parent)
{
    m_vecScaleRate << 0.25 << 0.5 << 0.75 << 1.0 << 1.5 << 2.0 << 2.5 << 3.0 << 4.0 << 6.0 << 8.0;
    m_nScaleIndex = 3;

    setDragMode(QGraphicsView::ScrollHandDrag);
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

    connect(horizontalScrollBar(), &QAbstractSlider::valueChanged, this, &MyGraphicsView::on_slider_valueChanged);
    connect(verticalScrollBar(), &QAbstractSlider::valueChanged, this, &MyGraphicsView::on_slider_valueChanged);
}

void MyGraphicsView::wheelEvent(QWheelEvent *event)
{
    CalculateViewportScale(event);
    on_slider_valueChanged();
}

void MyGraphicsView::resizeEvent(QResizeEvent *event)
{
    QGraphicsView::resizeEvent(event);
    on_slider_valueChanged();
}

void MyGraphicsView::contextMenuEvent(QContextMenuEvent *event)
{
    QAction* pActionOverBurden = new QAction;
    pActionOverBurden->setCheckable(true);
    pActionOverBurden->setChecked(emit getOverBurdenEnable());
    pActionOverBurden->setText("过爆点红色显示");

    QMenu* pMenuContext = new QMenu;
    pMenuContext->addAction(pActionOverBurden);

    pMenuContext->exec(QCursor::pos());
    event->accept();

    emit setOverBurdenEnable(pActionOverBurden->isChecked());
}

void MyGraphicsView::CalculateViewportScale(QWheelEvent *event)
{
    double dRelativeRate = 0.0;
    int nDestIndex = 0;
    if (event->angleDelta().ry() < 0) {
        nDestIndex = m_nScaleIndex - 1;
        if (nDestIndex < 0) {
            nDestIndex = 0;
            return;
        }
    } else if (event->angleDelta().ry() > 0) {
        nDestIndex = m_nScaleIndex + 1;
        if (nDestIndex > m_vecScaleRate.size() - 1) {
            nDestIndex = m_vecScaleRate.size() - 1;
            return;
        }
    }
    double currentScaleRate = m_vecScaleRate.at(m_nScaleIndex);
    double destScaleRate = m_vecScaleRate.at(nDestIndex);
    dRelativeRate = destScaleRate / currentScaleRate;
    m_nScaleIndex = nDestIndex;
    scale(dRelativeRate, dRelativeRate);
}

void MyGraphicsView::on_previewMoved(QRect rect)
{
    double currentScaleRate = m_vecScaleRate.at(m_nScaleIndex);
    horizontalScrollBar()->setValue(rect.x() * currentScaleRate);
    verticalScrollBar()->setValue(rect.y() * currentScaleRate);
}

void MyGraphicsView::on_slider_valueChanged()
{
    if (!isVisible()) {
        return;
    }
    QRect rectViewport;
    QRectF rectScene = sceneRect();
    if (horizontalScrollBar()->isHidden()) {
        rectViewport.setX(rectScene.x());
        rectViewport.setWidth(rectScene.width());
    } else {
        int nScaleWidth = horizontalScrollBar()->pageStep() + horizontalScrollBar()->maximum();
        double dScaleRate = double(nScaleWidth) / rectScene.width();
        rectViewport.setX(horizontalScrollBar()->value() / dScaleRate);
        rectViewport.setWidth(horizontalScrollBar()->pageStep() / dScaleRate);
    }
    if (verticalScrollBar()->isHidden()) {
        rectViewport.setY(0);
        rectViewport.setHeight(rectScene.height());
    } else {
        int nScaleHeight = verticalScrollBar()->pageStep() + verticalScrollBar()->maximum();
        double dScaleRate = double(nScaleHeight) / rectScene.height();
        rectViewport.setY(verticalScrollBar()->value() / dScaleRate);
        rectViewport.setHeight(verticalScrollBar()->pageStep() / dScaleRate);
    }
    emit setPreviewRect(rectViewport);
}

void MyGraphicsView::fitInView()
{
    QRectF rect = scene()->itemsBoundingRect();
    setSceneRect(rect);
    scene()->setSceneRect(rect);
}
